package cn.edu.buaa.purain.rest;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;



public class PurainRestFilter implements Filter {
	private static PurainServletFactory servletFactory = null;
	
	public void init(FilterConfig config) throws ServletException {
		String restHttpHeaderClassName = config.getInitParameter("restHttpHeaderClassName");
		
		if (null == restHttpHeaderClassName || "".equals(restHttpHeaderClassName)) {
			
			//if not set, use default class
			restHttpHeaderClassName = BasicPurainHttpHeader.class.getName();
			
		}
		
		String scanPackage = config.getInitParameter("scanPackage");
		if (null == scanPackage || "".equals(scanPackage)) {
			
			throw new ServletException("Error: scanPackage must be setted in web.xml");

		}
		
		PurainHttpHeader rhp;
		try {
			rhp = (PurainHttpHeader)Class.forName(restHttpHeaderClassName).newInstance();
			
			PurainHttpHeaderHelper.init(rhp);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (TooManyHttpHeaderFieldException e) {
			e.printStackTrace();
		}
		
		servletFactory = new AnnotationServletFactory(scanPackage);
		
		//servletFactory.dump();
		
		config.getServletContext().setAttribute("servletFactory", servletFactory);
	}

	@SuppressWarnings("unchecked")
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest request = (HttpServletRequest) req;
		
		/*String realUrl = request.getRequestURI().replaceFirst(request.getContextPath(), "");
		String s = realUrl.substring(1);
		String path = s.substring(s.indexOf("/"));*/
		
		String path = request.getServletPath();
		
		if (path.contains("*")) {
			throw new ServletException("wrong path exception, path cannot contain the character '*'.");
		}
		
		//bad design, proxy multi path to two path
		/*if (path.split("/").length > 3) {              
			path = "/xyz123mmmmmmmmmm321zyx/xyz123nnnnnnnnnn321zyx";
		}*/
		
		Enumeration<String> httpParameterNames = request.getHeaderNames();
		String key = PurainUrlHelper.httpPara2String(httpParameterNames);
		key = key + path;
		HttpServlet servlet = servletFactory.getServlet(key);
		
		if (servlet != null) {
			servlet.service(req, res);
		}else {
			chain.doFilter(req, res);
		}
	}

	public void destroy() {
		if (servletFactory != null) {
			servletFactory.getRealPathMap().clear();
			servletFactory.getRegexMap().clear();
		}
	}
}